lib/sign: enable verification for pulling
authorDenis Pynkin <denis.pynkin@collabora.com>
Thu, 1 Aug 2019 23:16:56 +0000 (02:16 +0300)
committerDenis Pynkin <denis.pynkin@collabora.com>
Wed, 25 Mar 2020 12:23:54 +0000 (15:23 +0300)
Signed-off-by: Denis Pynkin <denis.pynkin@collabora.com>
src/libostree/ostree-repo-pull.c
src/libostree/ostree-sign-dummy.c
src/libostree/ostree-sign-ed25519.c

index 381cce479cc7ea06dd5bb7d647b5dcbca6ebda1d..507bcc2e76057e38a2fde80cea97f1d3333d4a8c 100644 (file)
@@ -54,6 +54,8 @@
 #include <systemd/sd-journal.h>
 #endif
 
+#include "ostree-sign.h"
+
 #define OSTREE_MESSAGE_FETCH_COMPLETE_ID SD_ID128_MAKE(75,ba,3d,eb,0a,f0,41,a9,a4,62,72,ff,85,d9,e7,3e)
 
 #define OSTREE_REPO_PULL_CONTENT_PRIORITY  (OSTREE_FETCHER_DEFAULT_PRIORITY)
@@ -105,6 +107,7 @@ typedef struct {
 
   gboolean          gpg_verify;
   gboolean          gpg_verify_summary;
+  gboolean          sign_verify;
   gboolean          require_static_deltas;
   gboolean          disable_static_deltas;
   gboolean          has_tombstone_commits;
@@ -1500,6 +1503,38 @@ ostree_verify_unwritten_commit (OtPullData                 *pull_data,
     }
 #endif /* OSTREE_DISABLE_GPGME */
 
+  if (pull_data->sign_verify)
+    {
+      gboolean ret = FALSE;
+      g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit);
+      /* list all signature types in detached metadata and check if signed by any? */
+      GStrv names = ostree_sign_list_names();
+      for (guint i=0; i < g_strv_length (names); i++)
+        {
+          g_autoptr (OstreeSign) sign = ostree_sign_get_by_name (names[i], error);
+          g_autoptr(GVariant) signatures = NULL;
+          g_autofree gchar *signature_key = ostree_sign_metadata_key (sign);
+          g_autofree GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format (sign);
+
+          signatures = g_variant_lookup_value (detached_metadata,
+                                               signature_key,
+                                               signature_format);
+
+          /* Set return to true if any sign fit */
+          if (!signatures)
+            continue;
+
+          if (ostree_sign_metadata_verify (sign,
+                                           signed_data,
+                                           signatures,
+                                           error
+                                          ))
+            ret = TRUE;
+        }
+      g_strfreev(names);
+      return ret;
+    }
+
   return TRUE;
 }
 
@@ -1829,6 +1864,28 @@ scan_commit_object (OtPullData                 *pull_data,
     }
 #endif /* OSTREE_DISABLE_GPGME */
 
+  if (pull_data->sign_verify &&
+      !g_hash_table_contains (pull_data->verified_commits, checksum))
+    {
+      gboolean ret = FALSE;
+      /* list all signature types in detached metadata and check if signed by any? */
+      GStrv names = ostree_sign_list_names();
+      for (guint i=0; i < g_strv_length (names); i++)
+        {
+          g_autoptr (OstreeSign) sign = ostree_sign_get_by_name (names[i], error);
+
+          if (ostree_sign_commit_verify (sign,
+                                         pull_data->repo,
+                                         checksum,
+                                         cancellable,
+                                         error))
+            ret = TRUE;
+        }
+      g_strfreev(names);
+      if (ret == FALSE)
+        return FALSE;
+    }
+
   /* If we found a legacy transaction flag, assume we have to scan.
    * We always do a scan of dirtree objects; see
    * https://github.com/ostreedev/ostree/issues/543
@@ -3576,6 +3633,7 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
   g_autoptr(GSource) update_timeout = NULL;
   gboolean opt_gpg_verify_set = FALSE;
   gboolean opt_gpg_verify_summary_set = FALSE;
+  gboolean opt_sign_verify_set = FALSE;
   gboolean opt_collection_refs_set = FALSE;
   gboolean opt_n_network_retries_set = FALSE;
   gboolean opt_ref_keyring_map_set = FALSE;
@@ -3610,6 +3668,8 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
         g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify);
       opt_gpg_verify_summary_set =
         g_variant_lookup (options, "gpg-verify-summary", "b", &pull_data->gpg_verify_summary);
+      opt_sign_verify_set =
+        g_variant_lookup (options, "sign-verify", "b", &pull_data->sign_verify);
       (void) g_variant_lookup (options, "depth", "i", &pull_data->maxdepth);
       (void) g_variant_lookup (options, "disable-static-deltas", "b", &pull_data->disable_static_deltas);
       (void) g_variant_lookup (options, "require-static-deltas", "b", &pull_data->require_static_deltas);
@@ -3759,7 +3819,10 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
       /* For compatibility with pull-local, don't gpg verify local
        * pulls by default.
        */
-      if ((pull_data->gpg_verify || pull_data->gpg_verify_summary) &&
+      if ((pull_data->gpg_verify ||
+           pull_data->gpg_verify_summary ||
+           pull_data->sign_verify
+          ) &&
           pull_data->remote_name == NULL)
         {
           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -3788,6 +3851,10 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
           goto out;
 #endif /* OSTREE_DISABLE_GPGME */
 
+      /* TODO: read option for remote. */
+      if (!opt_sign_verify_set)
+        opt_sign_verify_set = TRUE;
+
       /* NOTE: If changing this, see the matching implementation in
        * ostree-sysroot-upgrader.c
        */
@@ -4647,23 +4714,28 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
         g_string_append_printf (msg, "libostree pull from '%s' for %u refs complete",
                                 pull_data->remote_name, g_hash_table_size (requested_refs_to_fetch));
 
-      const char *verify_state;
+      const char *gpg_verify_state;
 #ifndef OSTREE_DISABLE_GPGME
       if (pull_data->gpg_verify_summary)
         {
           if (pull_data->gpg_verify)
-            verify_state = "summary+commit";
+            gpg_verify_state = "summary+commit";
           else
-            verify_state = "summary-only";
+            gpg_verify_state = "summary-only";
         }
       else
-        verify_state = (pull_data->gpg_verify ? "commit" : "disabled");
-      g_string_append_printf (msg, "\nsecurity: GPG: %s ", verify_state);
+        gpg_verify_state = (pull_data->gpg_verify ? "commit" : "disabled");
+
+      g_string_append_printf (msg, "\nsecurity: GPG: %s ", gpg_verify_state);
 #else
-      verify_state = "disabled";
-      g_string_append_printf (msg, "\nsecurity: %s ", verify_state);
+      gpg_verify_state = "disabled";
+      g_string_append_printf (msg, "\nsecurity: %s ", gpg_verify_state);
 #endif /* OSTREE_DISABLE_GPGME */
 
+      const char *sign_verify_state;
+      sign_verify_state = (pull_data->sign_verify ? "commit" : "disabled");
+      g_string_append_printf (msg, "\nsecurity: SIGN: %s ", sign_verify_state);
+
       OstreeFetcherURI *first_uri = pull_data->meta_mirrorlist->pdata[0];
       g_autofree char *first_scheme = _ostree_fetcher_uri_get_scheme (first_uri);
       if (g_str_has_prefix (first_scheme, "http"))
@@ -4698,7 +4770,8 @@ ostree_repo_pull_with_options (OstreeRepo             *self,
       ot_journal_send ("MESSAGE=%s", msg->str,
                        "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_MESSAGE_FETCH_COMPLETE_ID),
                        "OSTREE_REMOTE=%s", pull_data->remote_name,
-                       "OSTREE_GPG=%s", verify_state,
+                       "OSTREE_SIGN=%s", sign_verify_state,
+                       "OSTREE_GPG=%s", gpg_verify_state,
                        "OSTREE_SECONDS=%u", n_seconds,
                        "OSTREE_XFER_SIZE=%s", formatted_xferred,
                        NULL);
@@ -6023,6 +6096,7 @@ ostree_repo_pull_from_remotes_async (OstreeRepo                           *self,
       g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", FALSE);
 #endif /* OSTREE_DISABLE_GPGME */
       g_variant_dict_insert (&local_options_dict, "gpg-verify-summary", "b", FALSE);
+      g_variant_dict_insert (&local_options_dict, "sign-verify", "b", FALSE);
       g_variant_dict_insert (&local_options_dict, "inherit-transaction", "b", TRUE);
       if (result->remote->refspec_name != NULL)
         g_variant_dict_insert (&local_options_dict, "override-remote-name", "s", result->remote->refspec_name);
index e489a988e21a4950ef931ed15f0c46a16f46e165..4baf656c71e4036089e95bddcb12e679c91e262a 100644 (file)
@@ -64,7 +64,6 @@ static void
 ostree_sign_dummy_class_init (OstreeSignDummyClass *self)
 {
   g_debug ("%s enter", __FUNCTION__);
-  GObjectClass *object_class = G_OBJECT_CLASS(self);
 }
 
 static void
index e3ab6b5716245331903df2dc4a24e79a6bf84235..6a110104ddb6c08a3b8cd5c50dafa5167dfe20ad 100644 (file)
@@ -67,7 +67,6 @@ static void
 ostree_sign_ed25519_class_init (OstreeSignEd25519Class *self)
 {
   g_debug ("%s enter", __FUNCTION__);
-  GObjectClass *object_class = G_OBJECT_CLASS(self);
 }
 
 static void